﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Jayden.Dll.Core.Collections.Generic
{
	public class BinaryTree<T> : IBinaryTree<T>
	{
		private T m_Value;
		private IBinaryTree<T> m_Parent;
		private IBinaryTree<T> m_Left;
		private IBinaryTree<T> m_Right;

		public BinaryTree(T item) { m_Value = item; }

		public IBinaryTree<T> Left
		{
			get { return m_Left; }
			set
			{
				if (m_Left == value)
					return;
				if (m_Left != null)
					m_Left.Parent = null;
				m_Left = value;
				if (m_Left != null)
					m_Left.Parent = this;
			}
		}
		public IBinaryTree<T> Right
		{
			get { return m_Right; }
			set
			{
				if (m_Right == value)
					return;
				if (m_Right != null)
					m_Right.Parent = null;
				m_Right = value;
				if (m_Right != null)
					m_Right.Parent = this;
			}
		}
		public IBinaryTree<T> Parent
		{
			get { return m_Parent; }
			set
			{
				if (m_Parent == value)
					return;
				m_Parent = value;
			}
		}
		ITree<T> ITree<T>.Parent { get { return m_Parent; } set { Parent = (IBinaryTree<T>)value; } }

		public T Value { get { return m_Value; } set { m_Value = value; } }

		public ITree<T> this[int index]
		{
			get { return index == 0 ? m_Left : m_Right; }
			set
			{
				if (index == 0)
					Left = (IBinaryTree<T>)value;
				else
					Right = (IBinaryTree<T>)value;
			}
		}

		public int Count { get { return 2; } }

		public bool IsLeaf { get { return m_Left == null && m_Right == null; } }

		public bool IsRoot { get { return m_Parent == null; } }
		ITree<T> ITree<T>.Root { get { return IsRoot ? this : m_Parent.Root; } }
		public IBinaryTree<T> Root { get { return IsRoot ? this : m_Parent.Root; } }

		public void AddChild(ITree<T> child) { throw new InvalidOperationException(); }
		public bool RemoveChild(ITree<T> child) { throw new InvalidOperationException(); }

		public delegate void TreeActionDelegate(T item);
		public void ExecuteLeftParentRight(TreeActionDelegate func)
		{
			if (Left != null)
				((BinaryTree<T>)Left).ExecuteLeftParentRight(func);
			func(m_Value);
			if (Right != null)
				((BinaryTree<T>)Left).ExecuteLeftParentRight(func);
		}
		public void ExecuteParentLeftRight(TreeActionDelegate func)
		{
			func(m_Value);
			if (Left != null)
				((BinaryTree<T>)Left).ExecuteParentLeftRight(func);
			if (Right != null)
				((BinaryTree<T>)Left).ExecuteParentLeftRight(func);
		}
		public void ExecuteRightParentLeft(TreeActionDelegate func)
		{
			if (Right != null)
				((BinaryTree<T>)Left).ExecuteRightParentLeft(func);
			func(m_Value);
			if (Left != null)
				((BinaryTree<T>)Left).ExecuteRightParentLeft(func);
		}
	}
}
